﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Data;
using System.Data.SqlClient;
using System.IO;

namespace SearchPlugin
{

    /**
     * Lightweight keyword-driven search framework for Siberia.
     * */

    public class SearchPluginRoutines
    {
        public string index_directory = ".\\index\\";
        public int staletime;
        public List<string> STOCK_LABELS = new List<string>(new string[] { "ID", "Name", "Description" });
        public List<int> STOCK_SCORES = new List<int>(new int[] { 0, 1, 10 });
        Dictionary<string, int> tendencies = new Dictionary<string, int>();


        public SearchPluginRoutines(int stale)
        {
            for (int i = 0; i < STOCK_LABELS.Count; i++)
            {
                tendencies.Add(STOCK_LABELS[i], STOCK_SCORES[i]);
            }
            staletime = stale;
        }

        public SearchPluginRoutines(List<string> labels, List<int> scores, int stale)
        {
            if (labels.Count != scores.Count) throw new ArgumentException("labels.count != scores.count");
            STOCK_LABELS.AddRange(labels);
            STOCK_SCORES.AddRange(scores);
            for (int i = 0; i < STOCK_LABELS.Count; i++)
            {
                tendencies.Add(STOCK_LABELS[i], STOCK_SCORES[i]);
            }
            staletime = stale;
        }
        public List<CMSSearchResult> RunSearch(string[] elements)
        {
            foreach (string str in elements)
            {
                //Guarantee we have up-to-date information in the index.
                if (File.Exists(index_directory + str + ".xml"))
                {
                    //see if the result is staletime minutes too old
                    //recache if necessary
                    FileInfo fi = new FileInfo(index_directory + str + ".xml");
                    if (DateTime.Now.Subtract(fi.CreationTime).Minutes >= staletime)
                    {
                        CrawlDatabase(str);
                    }
                }
                else
                {
                    //Cache.
                    CrawlDatabase(str);
                }
            }

            List<CMSSearchResult> searchlist = new List<CMSSearchResult>();

            foreach (string str in elements)
            {
                getTermResult(str);
            }
            return searchlist;
        }


        //Updates the index with the most recent search data for a given query.
        //Handles raw Content, not Pages, but the whole codebase is so fragmented,
        //I don't even know how I would go from Page to Content.
        //In any case, future implementations would be agnostic of the proper
        //relationship.
        public void CrawlDatabase(string query)
        {
            //Here, I would be calling an SQL query to grab stuff that even remotely contains this word,
            //and then caching the results in a lightweight flatfile.
            //Instead, we're just getting all of the data from our testbench and calling it a night.
            //The API was never implemented.

            //Here, I'd be interacting with the Data Layer.
            List<Dictionary<string, string>> queryresult = doLikeQuery(query);


            //Create an XML file.
            XmlTextWriter xtw = new XmlTextWriter(index_directory + query + ".xml", Encoding.UTF8);
            xtw.WriteStartDocument();
            xtw.WriteStartElement("scores");
            //We assume that each Dictionary<string, string> aka Content has an "ID" field.
            //From here, we create CMSSearchResults which are basically
            //Score/ID pairs.
            foreach (Dictionary<string, string> thing in queryresult)
            {
                xtw.WriteStartElement("element");
                Int32 score = 0;

                //Obtain a scoring.
                foreach (KeyValuePair<string, int> tendencypair in tendencies)
                {
                    if (thing.ContainsKey(tendencypair.Key))
                    {
                        if (thing[tendencypair.Key].Contains(query))
                        {
                            score += tendencies[tendencypair.Key];
                        }
                    }
                }

                //Write to the XML file.
                xtw.WriteElementString("ID", thing["ID"].ToString());
                xtw.WriteElementString("score", score.ToString());
                xtw.WriteEndElement();
            }
            xtw.WriteEndElement();
            xtw.WriteEndDocument();
            xtw.Close();
        }

        public List<CMSSearchResult> getTermResult(string query)
        {
            List<CMSSearchResult> resultslist = new List<CMSSearchResult>();
            XmlTextReader xtr = new XmlTextReader(index_directory + query + ".xml");
            XmlDocument xd = new XmlDocument();
            xd.Load(xtr);
            XmlNodeList xnl = xd.ChildNodes;
            //TODO: Somehow parse XML in a sane manner.

            return resultslist;

        }

        //Simulates a "LIKE" SQL query on a fake DB.
        //Yeah, it's ugly. So sue me.
        public List<Dictionary<string, string>> doLikeQuery(string term)
        {
            List<Dictionary<string, string>> items = getIndexData();
            List<Dictionary<string, string>> returnlist = new List<Dictionary<string, string>>();

            foreach(Dictionary<string, string> elem in items)
            {
                foreach (KeyValuePair<string, string> field in elem)
                {
                    if (field.Value.ToLower().Contains(term.ToLower()))
                    {
                        returnlist.Add(elem);
                        break;
                    }
                }
            }
            return returnlist;
        }

        //Returns all of the data in our "database".
        public List<Dictionary<string, string>> getIndexData()
        {
            List<Dictionary<string, string>> itemlist = new List<Dictionary<string, string>>();

            Dictionary<string, string> item = new Dictionary<string, string>();

            item.Add("ID", "1");
            item.Add("Name", "Violent Acres");
            item.Add("link", "http://www.violentacres.com");
            item.Add("Description", "Like You, But With Poor Impulse Control");
            item.Add("copyright", "Copyright 2005 Violent Acres");
            item.Add("ttl", "300");

            itemlist.Add(item);

            Dictionary<string, string> childitem1 = new Dictionary<string, string>();

            childitem1.Add("ID", "2");
            childitem1.Add("Name", "Violent Acres 234234234");
            childitem1.Add("link", "http://www.violentacres.com/Top");
            childitem1.Add("Description", "Like You, But With Poor Impulse Control");
            childitem1.Add("pubDate", "5/20/2011");
            childitem1.Add("author", "Bob");
            childitem1.Add("category", "Emo");

            itemlist.Add(childitem1);


            Dictionary<string, string> childitem2 = new Dictionary<string, string>();

            childitem2.Add("ID", "3");
            childitem2.Add("Name", "Drexel");
            childitem2.Add("link", "http://www.drexel.com");
            childitem2.Add("Description", "Join us! It doesn't hurt anymore.");
            childitem2.Add("pubDate", "5/18/2011");
            childitem2.Add("author", "James");
            childitem2.Add("category", "Emo");

            itemlist.Add(childitem2);

            return itemlist;

        }
    }
}
